package com.wskj.workbench.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.wskj.common.core.domain.entity.SysUser;
import com.wskj.common.core.mybatisplus.core.ServicePlusImpl;
import com.wskj.common.core.page.PagePlus;
import com.wskj.common.core.page.TableDataInfo;
import com.wskj.common.utils.common.AssertUtils;
import com.wskj.common.utils.common.PageUtils;
import com.wskj.common.utils.common.SecurityUtils;
import com.wskj.common.utils.tool.Query;
import com.wskj.system.service.ISysConfigService;
import com.wskj.system.service.ISysUserService;
import com.wskj.workbench.bo.app.AppTbUserWithdrawalAddBo;
import com.wskj.workbench.bo.app.AppTbUserWithdrawalQueryBo;
import com.wskj.workbench.bo.web.TbUserWithdrawalAddBo;
import com.wskj.workbench.bo.web.TbUserWithdrawalEditBo;
import com.wskj.workbench.bo.web.TbUserWithdrawalQueryBo;
import com.wskj.workbench.domain.TbUserJoinOrder;
import com.wskj.workbench.domain.TbUserWalletDetail;
import com.wskj.workbench.domain.TbUserWithdrawal;
import com.wskj.workbench.enums.UserWalletDetailDetailTypeEnum;
import com.wskj.workbench.enums.UserWithdrawalWithStatusEnum;
import com.wskj.workbench.mapper.TbUserWithdrawalMapper;
import com.wskj.workbench.service.ITbUserWalletDetailService;
import com.wskj.workbench.service.ITbUserWithdrawalService;
import com.wskj.workbench.vo.app.AppTbUserWithdrawalVo;
import com.wskj.workbench.vo.web.TbUserWithdrawalVo;
import lombok.AllArgsConstructor;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 用户提现记录Service业务层处理
 *
 * @author wskj
 * @date 2024-09-26
 */
@Service
@AllArgsConstructor(onConstructor_ = {@Lazy})
public class TbUserWithdrawalServiceImpl extends ServicePlusImpl<TbUserWithdrawalMapper, TbUserWithdrawal> implements ITbUserWithdrawalService {
    private final ISysUserService sysUserService;

    private final ISysConfigService sysConfigService;

    private final ITbUserWalletDetailService userWalletDetailService;

    private final ITbUserWithdrawalService tbUserWithdrawalService;

    @Override
    public TbUserWithdrawalVo queryById(Long id) {
        return getVoById(id, TbUserWithdrawalVo.class);
    }

    @Override
    public TableDataInfo<TbUserWithdrawalVo> queryPageList(TbUserWithdrawalQueryBo bo) {
        PagePlus<TbUserWithdrawal, TbUserWithdrawalVo> result = pageVo(PageUtils.buildPagePlus(), buildQueryWrapper(bo), TbUserWithdrawalVo.class);
        return PageUtils.buildDataInfo(result);
    }

    @Override
    public List<TbUserWithdrawalVo> queryList(TbUserWithdrawalQueryBo bo) {
        return listVo(buildQueryWrapper(bo), TbUserWithdrawalVo.class);
    }

    private LambdaQueryWrapper<TbUserWithdrawal> buildQueryWrapper(TbUserWithdrawalQueryBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<TbUserWithdrawal> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getUserId() != null, TbUserWithdrawal::getUserId, bo.getUserId());
        lqw.eq(StrUtil.isNotBlank(bo.getPhoneNumber()), TbUserWithdrawal::getPhoneNumber, bo.getPhoneNumber());
        lqw.like(StrUtil.isNotBlank(bo.getRealName()), TbUserWithdrawal::getRealName, bo.getRealName());
        lqw.eq(bo.getWithPrice() != null, TbUserWithdrawal::getWithPrice, bo.getWithPrice());
        lqw.eq(bo.getCommPrice() != null, TbUserWithdrawal::getCommPrice, bo.getCommPrice());
        lqw.eq(StrUtil.isNotBlank(bo.getWxqrUrl()), TbUserWithdrawal::getWxqrUrl, bo.getWxqrUrl());
        lqw.eq(StrUtil.isNotBlank(bo.getInvoiceUrl()), TbUserWithdrawal::getInvoiceUrl, bo.getInvoiceUrl());
        lqw.eq(StrUtil.isNotBlank(bo.getDelFlag()), TbUserWithdrawal::getDelFlag, bo.getDelFlag());

        // 如果不是超级管理员 需要查询所有下级用户列表
        if (!SecurityUtils.isAdmin(SecurityUtils.getUserId())) {

            SysUser sysUser = sysUserService.selectUserById(SecurityUtils.getUserId());

            String inviteFullCode = sysUser.getInviteFullCode() + sysUser.getInviteCode();

            // 所有的用户下级
            List<Long> userIds = sysUserService.list(Wrappers.lambdaQuery(SysUser.class).likeRight(SysUser::getInviteFullCode, inviteFullCode)).stream()
                    .map(SysUser::getUserId).collect(Collectors.toList());

            if (ObjectUtil.isEmpty(userIds)) {
                lqw.in(TbUserWithdrawal::getUserId, 0);
            } else {
                lqw.in(ObjectUtil.isNotEmpty(userIds), TbUserWithdrawal::getUserId, userIds);
            }
        }
        lqw.orderByDesc(TbUserWithdrawal::getCreateTime);
        lqw.eq(StrUtil.isNotBlank(bo.getWithStatus()), TbUserWithdrawal::getWithStatus, bo.getWithStatus());


        return lqw;
    }

    private LambdaQueryWrapper<TbUserWithdrawal> buildAppQueryWrapper(AppTbUserWithdrawalQueryBo bo) {
        LambdaQueryWrapper<TbUserWithdrawal> lqw = Wrappers.lambdaQuery();
        lqw.eq(TbUserWithdrawal::getUserId, SecurityUtils.getUserId());
        return lqw;
    }


    @Override
    public Boolean insertByAddBo(TbUserWithdrawalAddBo bo) {
        TbUserWithdrawal add = BeanUtil.toBean(bo, TbUserWithdrawal.class);
        validEntityBeforeSave(add);
        return save(add);
    }

    @Override
    public Boolean updateByEditBo(TbUserWithdrawalEditBo bo) {
        TbUserWithdrawal update = BeanUtil.toBean(bo, TbUserWithdrawal.class);
        validEntityBeforeSave(update);
        return updateById(update);
    }

    /**
     * 保存前的数据校验
     *
     * @param entity 实体类数据
     */
    private void validEntityBeforeSave(TbUserWithdrawal entity) {
        //TODO 做一些数据校验,如唯一约束
    }

    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return removeByIds(ids);
    }

    @Override
    public String importTbUserWithdrawal(List<TbUserWithdrawalVo> tbUserWithdrawalList) {
        AssertUtils.isTrue(CollectionUtils.isNotEmpty(tbUserWithdrawalList), "导入数据不能为空");
        int successNum = 0;
        for (TbUserWithdrawalVo tbUserWithdrawal : tbUserWithdrawalList) {
            TbUserWithdrawal add = BeanUtil.toBean(tbUserWithdrawal, TbUserWithdrawal.class);
            save(add);
            successNum++;
        }
        String msg = String.format("导入完成，共计 %d 条数据，成功 %d 条！", tbUserWithdrawalList.size(), successNum);
        if (successNum != tbUserWithdrawalList.size()) {
            msg = msg + String.format("失败 %d 条！", tbUserWithdrawalList.size() - successNum);
        }
        return msg;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean audit(TbUserWithdrawalEditBo bo) {
        TbUserWithdrawal tbUserWithdrawal = getById(bo.getId());
        tbUserWithdrawal.setWithStatus(bo.getWithStatus());
        tbUserWithdrawal.setReviewReason(bo.getReviewReason());
        boolean result = updateById(tbUserWithdrawal);
        Long userId = SecurityUtils.getUserId();
        SysUser sysUser = sysUserService.getById(userId);
        // 如果审核不通过余额再加回去
        if (bo.getWithStatus().equals(UserWithdrawalWithStatusEnum.SHENHEBUTONGGUO.getValue())) {
            sysUser.setTotalAmount(sysUser.getTotalAmount().add(tbUserWithdrawal.getWithPrice()));
            sysUserService.updateById(sysUser);
        } else if (bo.getWithStatus().equals(UserWithdrawalWithStatusEnum.SHENHETONGGUO.getValue())) {

            // 记录用户收入明细 减少
            TbUserWalletDetail tbUserWalletDetail = new TbUserWalletDetail();
            tbUserWalletDetail.setUserId(tbUserWithdrawal.getUserId());
            tbUserWalletDetail.setPhoneNumber(sysUser.getPhoneNumber());
            tbUserWalletDetail.setRealName(sysUser.getRealName());
            tbUserWalletDetail.setDetailType(UserWalletDetailDetailTypeEnum.TIXIAN.getValue());
            tbUserWalletDetail.setDetailPrice(tbUserWithdrawal.getWithPrice());
            userWalletDetailService.save(tbUserWalletDetail);
        }
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean applyWithdrawal(AppTbUserWithdrawalAddBo bo) {
        TbUserWithdrawal tbUserWithdrawal = BeanUtil.copyProperties(bo, TbUserWithdrawal.class);

        SysUser sysUser = sysUserService.getById(SecurityUtils.getUserId());

        tbUserWithdrawal.setUserId(sysUser.getUserId());
        tbUserWithdrawal.setPhoneNumber(sysUser.getPhoneNumber());
        tbUserWithdrawal.setRealName(sysUser.getRealName());

        // 用户赚的钱
        BigDecimal zhunPrice = userWalletDetailService.list(Wrappers.lambdaQuery(TbUserWalletDetail.class)
                .isNotNull(TbUserWalletDetail::getRecommendType)
                .eq(TbUserWalletDetail::getUserId, sysUser.getUserId())
                .eq(TbUserWalletDetail::getDelFlag, 0)
                .ne(TbUserWalletDetail::getDetailType, UserWalletDetailDetailTypeEnum.TIXIAN.getValue())

        ).stream().map(TbUserWalletDetail::getDetailPrice).reduce(BigDecimal.ZERO, BigDecimal::add);

        // 用户提现的钱 (排除审核不通过的)
        List<TbUserWithdrawal> list = tbUserWithdrawalService.list(Wrappers.lambdaQuery(TbUserWithdrawal.class)
                .ne(TbUserWithdrawal::getWithStatus, UserWithdrawalWithStatusEnum.SHENHEBUTONGGUO.getValue()).eq(TbUserWithdrawal::getUserId, sysUser.getUserId()));

        BigDecimal tixianPrice = list.stream().map(TbUserWithdrawal::getWithPrice).reduce(BigDecimal.ZERO, BigDecimal::add);

        // 目前余额
        BigDecimal muqian = zhunPrice.subtract(tixianPrice);
        AssertUtils.isTrue(muqian.compareTo(bo.getWithPrice()) >= 0, "用户余额不足,不能发起提现");


        // 没有上传发票的话扣税点
        if (ObjectUtil.isEmpty(bo.getInvoiceUrl())) {

            String percent = sysConfigService.selectConfigByKey("pingtai_percent");

            BigDecimal pingtai = bo.getWithPrice().multiply(new BigDecimal(percent).divide(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP));

            tbUserWithdrawal.setTaxPrice(pingtai);

        } else {
            tbUserWithdrawal.setTaxPrice(BigDecimal.ZERO);
        }

        String percent = sysConfigService.selectConfigByKey("with_amount");
        BigDecimal shouxufei = bo.getWithPrice().multiply(new BigDecimal(percent).divide(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP));
        tbUserWithdrawal.setCommPrice(shouxufei);


        // 实际应转金额 = 提现金额-税点-提现手续费
        BigDecimal realityPrice = tbUserWithdrawal.getWithPrice().subtract(tbUserWithdrawal.getTaxPrice()).subtract(tbUserWithdrawal.getCommPrice());
        tbUserWithdrawal.setRealityPrice(realityPrice);
        // 用户提现后剩余余额
        tbUserWithdrawal.setUserBalance(muqian.subtract(bo.getWithPrice()));
        boolean save = save(tbUserWithdrawal);


        // 用户余额减少
        sysUser.setTotalAmount(sysUser.getTotalAmount().subtract(bo.getWithPrice()));
        sysUserService.updateById(sysUser);

        return save;
    }

    /**
     * 查询某个用户的提现记录
     **/
    @Override
    public TableDataInfo<AppTbUserWithdrawalVo> withdrawalRecord(Query query, AppTbUserWithdrawalQueryBo bo) {
        PagePlus<TbUserWithdrawal, AppTbUserWithdrawalVo> result = pageVo(PageUtils.buildPagePlus(), buildAppQueryWrapper(bo), AppTbUserWithdrawalVo.class);
        return PageUtils.buildDataInfo(result);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean daozhang(TbUserWithdrawalEditBo bo) {
        TbUserWithdrawal tbUserWithdrawal = getById(bo.getId());
        AssertUtils.isTrue(tbUserWithdrawal.getWithStatus().equals(UserWithdrawalWithStatusEnum.SHENHETONGGUO.getValue()), "只有审核通过的提现记录才能操作到账");
        tbUserWithdrawal.setWithStatus(UserWithdrawalWithStatusEnum.TIXIANDAOZHANG.getValue());
        boolean result = updateById(tbUserWithdrawal);
        return result;
    }


}
